/* -*- C++ -*- */

//=============================================================================
/*
 * @author Feloweria <380374483@qq.com>
 * Copyright (C) Feloweria
 * 
 * $ID 2013-07-14 10:12:05 PM
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 * 
 * @version 1.0
 */
//=============================================================================

#include "Base/DateTime.h"
#include "Log/Log.h"

#ifdef __LINUX__
	#include <sys/time.h>
	#include <sys/errno.h>
#endif

#ifdef __WINDOWS__
	#include <time.h>
#endif

FELOWRIA_BEGIN
TimeValue  CurTime()
{
#ifdef __LINUX__
	timeval tv;
	struct timezone tz;

	if(-1 == gettimeofday(&tv,&tz))
	{
		if(errno == EFAULT)
			LOG_ERROR(" CurTime() LOG_ERROR::call \"gettimeofday\" One of tv or tz pointed outside the accessible address space");
		
		if(errno == EINVAL)
			LOG_ERROR(" CurTime() LOG_ERROR::call \"gettimeofday\" Timezone (or something else) is invalid");
		
		LOG_ERROR(" CurTime() LOG_ERROR::call \"gettimeofday\" LOG_ERROR");
	}
	
	TimeValue cur_time = tv.tv_sec * FELOWRIA_TIME_ONE_SECOND + tv.tv_usec * FELOWRIA_TIME_ONE_MICRO_SECOND - tz.tz_minuteswest * FELOWRIA_TIME_ONE_MINUTE;

	return cur_time;
#endif
	
#ifdef __WINDOWS__
	
	static bool init = true;
	static int64 start_time = 0;
	static int32 start_mirco_time = 0;

	if (init)
	{
		start_time = time(NULL);
		start_mirco_time = clock();
		init = false;
	}

	TimeValue cur_time = start_time * FELOWRIA_TIME_ONE_SECOND + (clock() - start_mirco_time) * FELOWRIA_TIME_ONE_MILLI_SECOND;

	return cur_time;
#endif
}

FELOWRIA_END

FELOWRIA_BEGIN

	static const int32 DAY_YEAR[YEAR_END + 1] = 
	{
		0,
		
		FELOWRIA_DAY_YEAR[YEAR_FIRST],
		
		FELOWRIA_DAY_YEAR[YEAR_FIRST] +
		FELOWRIA_DAY_YEAR[YEAR_SECOND],
		
		FELOWRIA_DAY_YEAR[YEAR_FIRST] +
		FELOWRIA_DAY_YEAR[YEAR_SECOND] +
		FELOWRIA_DAY_YEAR[YEAR_THIRD],
		
		FELOWRIA_DAY_YEAR[YEAR_FIRST] +
		FELOWRIA_DAY_YEAR[YEAR_SECOND] +
		FELOWRIA_DAY_YEAR[YEAR_THIRD] +
		FELOWRIA_DAY_YEAR[YEAR_FOUTH]
	};
	
	static const int32 DAY_LEAP_MONTH[MONTH_END + 1] = 
	{
		0,
		
		FELOWRIA_DAY_LEAP_MONTH[MONTH_JAN],
		
		FELOWRIA_DAY_LEAP_MONTH[MONTH_JAN] + 
		FELOWRIA_DAY_LEAP_MONTH[MONTH_FEB],
		
		FELOWRIA_DAY_LEAP_MONTH[MONTH_JAN] + 
		FELOWRIA_DAY_LEAP_MONTH[MONTH_FEB] +
		FELOWRIA_DAY_LEAP_MONTH[MONTH_MAR],
		
		
		FELOWRIA_DAY_LEAP_MONTH[MONTH_JAN] + 
		FELOWRIA_DAY_LEAP_MONTH[MONTH_FEB] +
		FELOWRIA_DAY_LEAP_MONTH[MONTH_MAR] +
		FELOWRIA_DAY_LEAP_MONTH[MONTH_APR],
		
		
		FELOWRIA_DAY_LEAP_MONTH[MONTH_JAN] + 
		FELOWRIA_DAY_LEAP_MONTH[MONTH_FEB] +
		FELOWRIA_DAY_LEAP_MONTH[MONTH_MAR] +
		FELOWRIA_DAY_LEAP_MONTH[MONTH_APR] +
		FELOWRIA_DAY_LEAP_MONTH[MONTH_MAY],
		
		
		FELOWRIA_DAY_LEAP_MONTH[MONTH_JAN] + 
		FELOWRIA_DAY_LEAP_MONTH[MONTH_FEB] +
		FELOWRIA_DAY_LEAP_MONTH[MONTH_MAR] +
		FELOWRIA_DAY_LEAP_MONTH[MONTH_APR] +
		FELOWRIA_DAY_LEAP_MONTH[MONTH_MAY] +
		FELOWRIA_DAY_LEAP_MONTH[MONTH_JUN],
		
		
		FELOWRIA_DAY_LEAP_MONTH[MONTH_JAN] + 
		FELOWRIA_DAY_LEAP_MONTH[MONTH_FEB] +
		FELOWRIA_DAY_LEAP_MONTH[MONTH_MAR] +
		FELOWRIA_DAY_LEAP_MONTH[MONTH_APR] +
		FELOWRIA_DAY_LEAP_MONTH[MONTH_MAY] +
		FELOWRIA_DAY_LEAP_MONTH[MONTH_JUN] +
		FELOWRIA_DAY_LEAP_MONTH[MONTH_JUL],
		
		
		FELOWRIA_DAY_LEAP_MONTH[MONTH_JAN] + 
		FELOWRIA_DAY_LEAP_MONTH[MONTH_FEB] +
		FELOWRIA_DAY_LEAP_MONTH[MONTH_MAR] +
		FELOWRIA_DAY_LEAP_MONTH[MONTH_APR] +
		FELOWRIA_DAY_LEAP_MONTH[MONTH_MAY] +
		FELOWRIA_DAY_LEAP_MONTH[MONTH_JUN] +
		FELOWRIA_DAY_LEAP_MONTH[MONTH_JUL] +
		FELOWRIA_DAY_LEAP_MONTH[MONTH_AUG],
		
		FELOWRIA_DAY_LEAP_MONTH[MONTH_JAN] + 
		FELOWRIA_DAY_LEAP_MONTH[MONTH_FEB] +
		FELOWRIA_DAY_LEAP_MONTH[MONTH_MAR] +
		FELOWRIA_DAY_LEAP_MONTH[MONTH_APR] +
		FELOWRIA_DAY_LEAP_MONTH[MONTH_MAY] +
		FELOWRIA_DAY_LEAP_MONTH[MONTH_JUN] +
		FELOWRIA_DAY_LEAP_MONTH[MONTH_JUL] +
		FELOWRIA_DAY_LEAP_MONTH[MONTH_AUG] +
		FELOWRIA_DAY_LEAP_MONTH[MONTH_SEP],
		
		FELOWRIA_DAY_LEAP_MONTH[MONTH_JAN] + 
		FELOWRIA_DAY_LEAP_MONTH[MONTH_FEB] +
		FELOWRIA_DAY_LEAP_MONTH[MONTH_MAR] +
		FELOWRIA_DAY_LEAP_MONTH[MONTH_APR] +
		FELOWRIA_DAY_LEAP_MONTH[MONTH_MAY] +
		FELOWRIA_DAY_LEAP_MONTH[MONTH_JUN] +
		FELOWRIA_DAY_LEAP_MONTH[MONTH_JUL] +
		FELOWRIA_DAY_LEAP_MONTH[MONTH_AUG] +
		FELOWRIA_DAY_LEAP_MONTH[MONTH_SEP] +
		FELOWRIA_DAY_LEAP_MONTH[MONTH_OCT],
		
		FELOWRIA_DAY_LEAP_MONTH[MONTH_JAN] + 
		FELOWRIA_DAY_LEAP_MONTH[MONTH_FEB] +
		FELOWRIA_DAY_LEAP_MONTH[MONTH_MAR] +
		FELOWRIA_DAY_LEAP_MONTH[MONTH_APR] +
		FELOWRIA_DAY_LEAP_MONTH[MONTH_MAY] +
		FELOWRIA_DAY_LEAP_MONTH[MONTH_JUN] +
		FELOWRIA_DAY_LEAP_MONTH[MONTH_JUL] +
		FELOWRIA_DAY_LEAP_MONTH[MONTH_AUG] +
		FELOWRIA_DAY_LEAP_MONTH[MONTH_SEP] +
		FELOWRIA_DAY_LEAP_MONTH[MONTH_OCT] +
		FELOWRIA_DAY_LEAP_MONTH[MONTH_NOV],
		
		FELOWRIA_DAY_LEAP_MONTH[MONTH_JAN] + 
		FELOWRIA_DAY_LEAP_MONTH[MONTH_FEB] +
		FELOWRIA_DAY_LEAP_MONTH[MONTH_MAR] +
		FELOWRIA_DAY_LEAP_MONTH[MONTH_APR] +
		FELOWRIA_DAY_LEAP_MONTH[MONTH_MAY] +
		FELOWRIA_DAY_LEAP_MONTH[MONTH_JUN] +
		FELOWRIA_DAY_LEAP_MONTH[MONTH_JUL] +
		FELOWRIA_DAY_LEAP_MONTH[MONTH_AUG] +
		FELOWRIA_DAY_LEAP_MONTH[MONTH_SEP] +
		FELOWRIA_DAY_LEAP_MONTH[MONTH_OCT] +
		FELOWRIA_DAY_LEAP_MONTH[MONTH_NOV] +
		FELOWRIA_DAY_LEAP_MONTH[MONTH_DEC],
	};
	
	static const int32 DAY_COMMON_MONTH[MONTH_END + 1] = 
	{
		0,
		
		FELOWRIA_DAY_COMMON_MONTH[MONTH_JAN],
		
		FELOWRIA_DAY_COMMON_MONTH[MONTH_JAN] + 
		FELOWRIA_DAY_COMMON_MONTH[MONTH_FEB],
		
		FELOWRIA_DAY_COMMON_MONTH[MONTH_JAN] + 
		FELOWRIA_DAY_COMMON_MONTH[MONTH_FEB] +
		FELOWRIA_DAY_COMMON_MONTH[MONTH_MAR],
		
		
		FELOWRIA_DAY_COMMON_MONTH[MONTH_JAN] + 
		FELOWRIA_DAY_COMMON_MONTH[MONTH_FEB] +
		FELOWRIA_DAY_COMMON_MONTH[MONTH_MAR] +
		FELOWRIA_DAY_COMMON_MONTH[MONTH_APR],
		
		
		FELOWRIA_DAY_COMMON_MONTH[MONTH_JAN] + 
		FELOWRIA_DAY_COMMON_MONTH[MONTH_FEB] +
		FELOWRIA_DAY_COMMON_MONTH[MONTH_MAR] +
		FELOWRIA_DAY_COMMON_MONTH[MONTH_APR] +
		FELOWRIA_DAY_COMMON_MONTH[MONTH_MAY],
		
		
		FELOWRIA_DAY_COMMON_MONTH[MONTH_JAN] + 
		FELOWRIA_DAY_COMMON_MONTH[MONTH_FEB] +
		FELOWRIA_DAY_COMMON_MONTH[MONTH_MAR] +
		FELOWRIA_DAY_COMMON_MONTH[MONTH_APR] +
		FELOWRIA_DAY_COMMON_MONTH[MONTH_MAY] +
		FELOWRIA_DAY_COMMON_MONTH[MONTH_JUN],
		
		
		FELOWRIA_DAY_COMMON_MONTH[MONTH_JAN] + 
		FELOWRIA_DAY_COMMON_MONTH[MONTH_FEB] +
		FELOWRIA_DAY_COMMON_MONTH[MONTH_MAR] +
		FELOWRIA_DAY_COMMON_MONTH[MONTH_APR] +
		FELOWRIA_DAY_COMMON_MONTH[MONTH_MAY] +
		FELOWRIA_DAY_COMMON_MONTH[MONTH_JUN] +
		FELOWRIA_DAY_COMMON_MONTH[MONTH_JUL],
		
		
		FELOWRIA_DAY_COMMON_MONTH[MONTH_JAN] + 
		FELOWRIA_DAY_COMMON_MONTH[MONTH_FEB] +
		FELOWRIA_DAY_COMMON_MONTH[MONTH_MAR] +
		FELOWRIA_DAY_COMMON_MONTH[MONTH_APR] +
		FELOWRIA_DAY_COMMON_MONTH[MONTH_MAY] +
		FELOWRIA_DAY_COMMON_MONTH[MONTH_JUN] +
		FELOWRIA_DAY_COMMON_MONTH[MONTH_JUL] +
		FELOWRIA_DAY_COMMON_MONTH[MONTH_AUG],
		
		FELOWRIA_DAY_COMMON_MONTH[MONTH_JAN] + 
		FELOWRIA_DAY_COMMON_MONTH[MONTH_FEB] +
		FELOWRIA_DAY_COMMON_MONTH[MONTH_MAR] +
		FELOWRIA_DAY_COMMON_MONTH[MONTH_APR] +
		FELOWRIA_DAY_COMMON_MONTH[MONTH_MAY] +
		FELOWRIA_DAY_COMMON_MONTH[MONTH_JUN] +
		FELOWRIA_DAY_COMMON_MONTH[MONTH_JUL] +
		FELOWRIA_DAY_COMMON_MONTH[MONTH_AUG] +
		FELOWRIA_DAY_COMMON_MONTH[MONTH_SEP],
		
		FELOWRIA_DAY_COMMON_MONTH[MONTH_JAN] + 
		FELOWRIA_DAY_COMMON_MONTH[MONTH_FEB] +
		FELOWRIA_DAY_COMMON_MONTH[MONTH_MAR] +
		FELOWRIA_DAY_COMMON_MONTH[MONTH_APR] +
		FELOWRIA_DAY_COMMON_MONTH[MONTH_MAY] +
		FELOWRIA_DAY_COMMON_MONTH[MONTH_JUN] +
		FELOWRIA_DAY_COMMON_MONTH[MONTH_JUL] +
		FELOWRIA_DAY_COMMON_MONTH[MONTH_AUG] +
		FELOWRIA_DAY_COMMON_MONTH[MONTH_SEP] +
		FELOWRIA_DAY_COMMON_MONTH[MONTH_OCT],
		
		FELOWRIA_DAY_COMMON_MONTH[MONTH_JAN] + 
		FELOWRIA_DAY_COMMON_MONTH[MONTH_FEB] +
		FELOWRIA_DAY_COMMON_MONTH[MONTH_MAR] +
		FELOWRIA_DAY_COMMON_MONTH[MONTH_APR] +
		FELOWRIA_DAY_COMMON_MONTH[MONTH_MAY] +
		FELOWRIA_DAY_COMMON_MONTH[MONTH_JUN] +
		FELOWRIA_DAY_COMMON_MONTH[MONTH_JUL] +
		FELOWRIA_DAY_COMMON_MONTH[MONTH_AUG] +
		FELOWRIA_DAY_COMMON_MONTH[MONTH_SEP] +
		FELOWRIA_DAY_COMMON_MONTH[MONTH_OCT] +
		FELOWRIA_DAY_COMMON_MONTH[MONTH_NOV],
		
		FELOWRIA_DAY_COMMON_MONTH[MONTH_JAN] + 
		FELOWRIA_DAY_COMMON_MONTH[MONTH_FEB] +
		FELOWRIA_DAY_COMMON_MONTH[MONTH_MAR] +
		FELOWRIA_DAY_COMMON_MONTH[MONTH_APR] +
		FELOWRIA_DAY_COMMON_MONTH[MONTH_MAY] +
		FELOWRIA_DAY_COMMON_MONTH[MONTH_JUN] +
		FELOWRIA_DAY_COMMON_MONTH[MONTH_JUL] +
		FELOWRIA_DAY_COMMON_MONTH[MONTH_AUG] +
		FELOWRIA_DAY_COMMON_MONTH[MONTH_SEP] +
		FELOWRIA_DAY_COMMON_MONTH[MONTH_OCT] +
		FELOWRIA_DAY_COMMON_MONTH[MONTH_NOV] +
		FELOWRIA_DAY_COMMON_MONTH[MONTH_DEC],
	};
	
	static const TimeValue TIME_YEAR[YEAR_END + 1] = 
	{
		0.0,
		
		FELOWRIA_TIME_YEAR[YEAR_FIRST],
		
		FELOWRIA_TIME_YEAR[YEAR_FIRST] + 
		FELOWRIA_TIME_YEAR[YEAR_SECOND],
		
		FELOWRIA_TIME_YEAR[YEAR_FIRST] + 
		FELOWRIA_TIME_YEAR[YEAR_SECOND] + 
		FELOWRIA_TIME_YEAR[YEAR_THIRD],
		
		FELOWRIA_TIME_YEAR[YEAR_FIRST] + 
		FELOWRIA_TIME_YEAR[YEAR_SECOND] + 
		FELOWRIA_TIME_YEAR[YEAR_THIRD] + 
		FELOWRIA_TIME_YEAR[YEAR_FOUTH]
	};
	
	static const TimeValue TIME_HUNDRED_YEAR[YEAR_HUNDRED_END + 1] = 
	{
		0,
		(DAY_YEAR[YEAR_END] * 25 - 1) * 1 * FELOWRIA_TIME_ONE_DAY,
		(DAY_YEAR[YEAR_END] * 25 - 1) * 2 * FELOWRIA_TIME_ONE_DAY,
		(DAY_YEAR[YEAR_END] * 25 - 1) * 3 * FELOWRIA_TIME_ONE_DAY,
		((DAY_YEAR[YEAR_END] * 25 - 1) * 4 + 1) * FELOWRIA_TIME_ONE_DAY,
		
	};
	
	static const TimeValue TIME_LEAP_MONTH[MONTH_END + 1] =
	{
		0.0,
		
		FELOWRIA_TIME_LEAP_ONE_MONTH[MONTH_JAN],
		
		FELOWRIA_TIME_LEAP_ONE_MONTH[MONTH_JAN] + 
		FELOWRIA_TIME_LEAP_ONE_MONTH[MONTH_FEB],
		
		FELOWRIA_TIME_LEAP_ONE_MONTH[MONTH_JAN] + 
		FELOWRIA_TIME_LEAP_ONE_MONTH[MONTH_FEB] +
		FELOWRIA_TIME_LEAP_ONE_MONTH[MONTH_MAR],
		
		FELOWRIA_TIME_LEAP_ONE_MONTH[MONTH_JAN] + 
		FELOWRIA_TIME_LEAP_ONE_MONTH[MONTH_FEB] +
		FELOWRIA_TIME_LEAP_ONE_MONTH[MONTH_MAR] +
		FELOWRIA_TIME_LEAP_ONE_MONTH[MONTH_APR],
		
		FELOWRIA_TIME_LEAP_ONE_MONTH[MONTH_JAN] + 
		FELOWRIA_TIME_LEAP_ONE_MONTH[MONTH_FEB] +
		FELOWRIA_TIME_LEAP_ONE_MONTH[MONTH_MAR] +
		FELOWRIA_TIME_LEAP_ONE_MONTH[MONTH_APR] +
		FELOWRIA_TIME_LEAP_ONE_MONTH[MONTH_MAY],
		
		FELOWRIA_TIME_LEAP_ONE_MONTH[MONTH_JAN] + 
		FELOWRIA_TIME_LEAP_ONE_MONTH[MONTH_FEB] +
		FELOWRIA_TIME_LEAP_ONE_MONTH[MONTH_MAR] +
		FELOWRIA_TIME_LEAP_ONE_MONTH[MONTH_APR] +
		FELOWRIA_TIME_LEAP_ONE_MONTH[MONTH_MAY] +
		FELOWRIA_TIME_LEAP_ONE_MONTH[MONTH_JUN],
		
		FELOWRIA_TIME_LEAP_ONE_MONTH[MONTH_JAN] + 
		FELOWRIA_TIME_LEAP_ONE_MONTH[MONTH_FEB] +
		FELOWRIA_TIME_LEAP_ONE_MONTH[MONTH_MAR] +
		FELOWRIA_TIME_LEAP_ONE_MONTH[MONTH_APR] +
		FELOWRIA_TIME_LEAP_ONE_MONTH[MONTH_MAY] +
		FELOWRIA_TIME_LEAP_ONE_MONTH[MONTH_JUN] +
		FELOWRIA_TIME_LEAP_ONE_MONTH[MONTH_JUL],
		
		FELOWRIA_TIME_LEAP_ONE_MONTH[MONTH_JAN] + 
		FELOWRIA_TIME_LEAP_ONE_MONTH[MONTH_FEB] +
		FELOWRIA_TIME_LEAP_ONE_MONTH[MONTH_MAR] +
		FELOWRIA_TIME_LEAP_ONE_MONTH[MONTH_APR] +
		FELOWRIA_TIME_LEAP_ONE_MONTH[MONTH_MAY] +
		FELOWRIA_TIME_LEAP_ONE_MONTH[MONTH_JUN] +
		FELOWRIA_TIME_LEAP_ONE_MONTH[MONTH_JUL] +
		FELOWRIA_TIME_LEAP_ONE_MONTH[MONTH_AUG],
		
		
		FELOWRIA_TIME_LEAP_ONE_MONTH[MONTH_JAN] + 
		FELOWRIA_TIME_LEAP_ONE_MONTH[MONTH_FEB] +
		FELOWRIA_TIME_LEAP_ONE_MONTH[MONTH_MAR] +
		FELOWRIA_TIME_LEAP_ONE_MONTH[MONTH_APR] +
		FELOWRIA_TIME_LEAP_ONE_MONTH[MONTH_MAY] +
		FELOWRIA_TIME_LEAP_ONE_MONTH[MONTH_JUN] +
		FELOWRIA_TIME_LEAP_ONE_MONTH[MONTH_JUL] +
		FELOWRIA_TIME_LEAP_ONE_MONTH[MONTH_AUG] +
		FELOWRIA_TIME_LEAP_ONE_MONTH[MONTH_SEP],
		
		
		FELOWRIA_TIME_LEAP_ONE_MONTH[MONTH_JAN] + 
		FELOWRIA_TIME_LEAP_ONE_MONTH[MONTH_FEB] +
		FELOWRIA_TIME_LEAP_ONE_MONTH[MONTH_MAR] +
		FELOWRIA_TIME_LEAP_ONE_MONTH[MONTH_APR] +
		FELOWRIA_TIME_LEAP_ONE_MONTH[MONTH_MAY] +
		FELOWRIA_TIME_LEAP_ONE_MONTH[MONTH_JUN] +
		FELOWRIA_TIME_LEAP_ONE_MONTH[MONTH_JUL] +
		FELOWRIA_TIME_LEAP_ONE_MONTH[MONTH_AUG] +
		FELOWRIA_TIME_LEAP_ONE_MONTH[MONTH_SEP] +
		FELOWRIA_TIME_LEAP_ONE_MONTH[MONTH_OCT],
		
		
		FELOWRIA_TIME_LEAP_ONE_MONTH[MONTH_JAN] + 
		FELOWRIA_TIME_LEAP_ONE_MONTH[MONTH_FEB] +
		FELOWRIA_TIME_LEAP_ONE_MONTH[MONTH_MAR] +
		FELOWRIA_TIME_LEAP_ONE_MONTH[MONTH_APR] +
		FELOWRIA_TIME_LEAP_ONE_MONTH[MONTH_MAY] +
		FELOWRIA_TIME_LEAP_ONE_MONTH[MONTH_JUN] +
		FELOWRIA_TIME_LEAP_ONE_MONTH[MONTH_JUL] +
		FELOWRIA_TIME_LEAP_ONE_MONTH[MONTH_AUG] +
		FELOWRIA_TIME_LEAP_ONE_MONTH[MONTH_SEP] +
		FELOWRIA_TIME_LEAP_ONE_MONTH[MONTH_OCT] +
		FELOWRIA_TIME_LEAP_ONE_MONTH[MONTH_NOV],
		
		FELOWRIA_TIME_LEAP_ONE_MONTH[MONTH_JAN] + 
		FELOWRIA_TIME_LEAP_ONE_MONTH[MONTH_FEB] +
		FELOWRIA_TIME_LEAP_ONE_MONTH[MONTH_MAR] +
		FELOWRIA_TIME_LEAP_ONE_MONTH[MONTH_APR] +
		FELOWRIA_TIME_LEAP_ONE_MONTH[MONTH_MAY] +
		FELOWRIA_TIME_LEAP_ONE_MONTH[MONTH_JUN] +
		FELOWRIA_TIME_LEAP_ONE_MONTH[MONTH_JUL] +
		FELOWRIA_TIME_LEAP_ONE_MONTH[MONTH_AUG] +
		FELOWRIA_TIME_LEAP_ONE_MONTH[MONTH_SEP] +
		FELOWRIA_TIME_LEAP_ONE_MONTH[MONTH_OCT] +
		FELOWRIA_TIME_LEAP_ONE_MONTH[MONTH_NOV] +
		FELOWRIA_TIME_LEAP_ONE_MONTH[MONTH_DEC]
	};

	static const TimeValue TIME_COMMON_MONTH[MONTH_END + 1] =
	{
		0.0,
		
		FELOWRIA_TIME_COMMON_ONE_MONTH[MONTH_JAN],
		
		FELOWRIA_TIME_COMMON_ONE_MONTH[MONTH_JAN] + 
		FELOWRIA_TIME_COMMON_ONE_MONTH[MONTH_FEB],
		
		FELOWRIA_TIME_COMMON_ONE_MONTH[MONTH_JAN] + 
		FELOWRIA_TIME_COMMON_ONE_MONTH[MONTH_FEB] +
		FELOWRIA_TIME_COMMON_ONE_MONTH[MONTH_MAR],
		
		FELOWRIA_TIME_COMMON_ONE_MONTH[MONTH_JAN] + 
		FELOWRIA_TIME_COMMON_ONE_MONTH[MONTH_FEB] +
		FELOWRIA_TIME_COMMON_ONE_MONTH[MONTH_MAR] +
		FELOWRIA_TIME_COMMON_ONE_MONTH[MONTH_APR],
		
		FELOWRIA_TIME_COMMON_ONE_MONTH[MONTH_JAN] + 
		FELOWRIA_TIME_COMMON_ONE_MONTH[MONTH_FEB] +
		FELOWRIA_TIME_COMMON_ONE_MONTH[MONTH_MAR] +
		FELOWRIA_TIME_COMMON_ONE_MONTH[MONTH_APR] +
		FELOWRIA_TIME_COMMON_ONE_MONTH[MONTH_MAY],
		
		FELOWRIA_TIME_COMMON_ONE_MONTH[MONTH_JAN] + 
		FELOWRIA_TIME_COMMON_ONE_MONTH[MONTH_FEB] +
		FELOWRIA_TIME_COMMON_ONE_MONTH[MONTH_MAR] +
		FELOWRIA_TIME_COMMON_ONE_MONTH[MONTH_APR] +
		FELOWRIA_TIME_COMMON_ONE_MONTH[MONTH_MAY] +
		FELOWRIA_TIME_COMMON_ONE_MONTH[MONTH_JUN],
		
		FELOWRIA_TIME_COMMON_ONE_MONTH[MONTH_JAN] + 
		FELOWRIA_TIME_COMMON_ONE_MONTH[MONTH_FEB] +
		FELOWRIA_TIME_COMMON_ONE_MONTH[MONTH_MAR] +
		FELOWRIA_TIME_COMMON_ONE_MONTH[MONTH_APR] +
		FELOWRIA_TIME_COMMON_ONE_MONTH[MONTH_MAY] +
		FELOWRIA_TIME_COMMON_ONE_MONTH[MONTH_JUN] +
		FELOWRIA_TIME_COMMON_ONE_MONTH[MONTH_JUL],
		
		FELOWRIA_TIME_COMMON_ONE_MONTH[MONTH_JAN] + 
		FELOWRIA_TIME_COMMON_ONE_MONTH[MONTH_FEB] +
		FELOWRIA_TIME_COMMON_ONE_MONTH[MONTH_MAR] +
		FELOWRIA_TIME_COMMON_ONE_MONTH[MONTH_APR] +
		FELOWRIA_TIME_COMMON_ONE_MONTH[MONTH_MAY] +
		FELOWRIA_TIME_COMMON_ONE_MONTH[MONTH_JUN] +
		FELOWRIA_TIME_COMMON_ONE_MONTH[MONTH_JUL] +
		FELOWRIA_TIME_COMMON_ONE_MONTH[MONTH_AUG],
		
		
		FELOWRIA_TIME_COMMON_ONE_MONTH[MONTH_JAN] + 
		FELOWRIA_TIME_COMMON_ONE_MONTH[MONTH_FEB] +
		FELOWRIA_TIME_COMMON_ONE_MONTH[MONTH_MAR] +
		FELOWRIA_TIME_COMMON_ONE_MONTH[MONTH_APR] +
		FELOWRIA_TIME_COMMON_ONE_MONTH[MONTH_MAY] +
		FELOWRIA_TIME_COMMON_ONE_MONTH[MONTH_JUN] +
		FELOWRIA_TIME_COMMON_ONE_MONTH[MONTH_JUL] +
		FELOWRIA_TIME_COMMON_ONE_MONTH[MONTH_AUG] +
		FELOWRIA_TIME_COMMON_ONE_MONTH[MONTH_SEP],
		
		
		FELOWRIA_TIME_COMMON_ONE_MONTH[MONTH_JAN] + 
		FELOWRIA_TIME_COMMON_ONE_MONTH[MONTH_FEB] +
		FELOWRIA_TIME_COMMON_ONE_MONTH[MONTH_MAR] +
		FELOWRIA_TIME_COMMON_ONE_MONTH[MONTH_APR] +
		FELOWRIA_TIME_COMMON_ONE_MONTH[MONTH_MAY] +
		FELOWRIA_TIME_COMMON_ONE_MONTH[MONTH_JUN] +
		FELOWRIA_TIME_COMMON_ONE_MONTH[MONTH_JUL] +
		FELOWRIA_TIME_COMMON_ONE_MONTH[MONTH_AUG] +
		FELOWRIA_TIME_COMMON_ONE_MONTH[MONTH_SEP] +
		FELOWRIA_TIME_COMMON_ONE_MONTH[MONTH_OCT],
		
		
		FELOWRIA_TIME_COMMON_ONE_MONTH[MONTH_JAN] + 
		FELOWRIA_TIME_COMMON_ONE_MONTH[MONTH_FEB] +
		FELOWRIA_TIME_COMMON_ONE_MONTH[MONTH_MAR] +
		FELOWRIA_TIME_COMMON_ONE_MONTH[MONTH_APR] +
		FELOWRIA_TIME_COMMON_ONE_MONTH[MONTH_MAY] +
		FELOWRIA_TIME_COMMON_ONE_MONTH[MONTH_JUN] +
		FELOWRIA_TIME_COMMON_ONE_MONTH[MONTH_JUL] +
		FELOWRIA_TIME_COMMON_ONE_MONTH[MONTH_AUG] +
		FELOWRIA_TIME_COMMON_ONE_MONTH[MONTH_SEP] +
		FELOWRIA_TIME_COMMON_ONE_MONTH[MONTH_OCT] +
		FELOWRIA_TIME_COMMON_ONE_MONTH[MONTH_NOV],
		
		FELOWRIA_TIME_COMMON_ONE_MONTH[MONTH_JAN] + 
		FELOWRIA_TIME_COMMON_ONE_MONTH[MONTH_FEB] +
		FELOWRIA_TIME_COMMON_ONE_MONTH[MONTH_MAR] +
		FELOWRIA_TIME_COMMON_ONE_MONTH[MONTH_APR] +
		FELOWRIA_TIME_COMMON_ONE_MONTH[MONTH_MAY] +
		FELOWRIA_TIME_COMMON_ONE_MONTH[MONTH_JUN] +
		FELOWRIA_TIME_COMMON_ONE_MONTH[MONTH_JUL] +
		FELOWRIA_TIME_COMMON_ONE_MONTH[MONTH_AUG] +
		FELOWRIA_TIME_COMMON_ONE_MONTH[MONTH_SEP] +
		FELOWRIA_TIME_COMMON_ONE_MONTH[MONTH_OCT] +
		FELOWRIA_TIME_COMMON_ONE_MONTH[MONTH_NOV] +
		FELOWRIA_TIME_COMMON_ONE_MONTH[MONTH_DEC]
	};
	
	static const TimeValue HUNDRED_YEARRD_STANDARD = 7 * TIME_YEAR[YEAR_END] + 
														FELOWRIA_TIME_YEAR[YEAR_FIRST] + 
														FELOWRIA_TIME_YEAR[YEAR_THIRD] + 
														FELOWRIA_TIME_YEAR[YEAR_FOUTH];//2001/1/1 0:0:0 year as standard


bool DateTime::Set(const int32 year,
		const int32 month,
		const int32 day,
		const int32 week_day,
		const int32 hour,
		const int32 minute,
		const int32 second,
		const int32 micro_second)
{
	bool isNegativeMonth = month % 12 <= 0;
	
	int32 year_left = year + month / MONTH_END - isNegativeMonth * 1;
	int32 tMonth = month % MONTH_END + isNegativeMonth * MONTH_END - 1;	///<minute one because MONTH_JAN begin at 1
	
	bool isLeapYear = (year_left % YEAR_END == 0 && year_left % ONE_HUNDREAD_YEAR != 0) || year_left % FOUR_HUNDREAD_YEAR == 0;
	
	year_left -= 2001;
	
	int32 four_hundred_year_offset = year_left / FOUR_HUNDREAD_YEAR + (year_left < 0) * (-1);
	int32 four_hundred_year_left = (year_left - four_hundred_year_offset * FOUR_HUNDREAD_YEAR) / ONE_HUNDREAD_YEAR;
	
	year_left = year_left - four_hundred_year_offset *  FOUR_HUNDREAD_YEAR - four_hundred_year_left * ONE_HUNDREAD_YEAR;
	
	bool isYearLeftNegative = year_left < 0;
	
	time = HUNDRED_YEARRD_STANDARD + 
			four_hundred_year_offset * TIME_HUNDRED_YEAR[YEAR_HUNDRED_END] + TIME_HUNDRED_YEAR[four_hundred_year_left] +
			((year_left - isYearLeftNegative * YEAR_END) / YEAR_END) * DAY_YEAR[YEAR_END] * FELOWRIA_TIME_ONE_DAY + 
			DAY_YEAR[year_left % YEAR_END + isYearLeftNegative * YEAR_END] * FELOWRIA_TIME_ONE_DAY +
			(isLeapYear ? DAY_LEAP_MONTH[tMonth] : DAY_COMMON_MONTH[tMonth]) * FELOWRIA_TIME_ONE_DAY +
			(day - 1)* FELOWRIA_TIME_ONE_DAY + ///<minute one because DAY begin at 1
			hour * FELOWRIA_TIME_ONE_HOUR + 
			minute * FELOWRIA_TIME_ONE_MINUTE + 
			second * FELOWRIA_TIME_ONE_SECOND +
			micro_second * FELOWRIA_TIME_ONE_MICRO_SECOND;
				
	return Set(time);
}


bool DateTime::Set(const TimeValue time_value)
{
	TimeValue time_left = time_value;
///<400 year process
	{
		time_left = time_left - HUNDRED_YEARRD_STANDARD;
		int32 year_hundred_offset =  static_cast<int32>(time_left / TIME_HUNDRED_YEAR[YEAR_HUNDRED_END] + (time_left < 0) * (-1));
		time_left = time_left - year_hundred_offset * TIME_HUNDRED_YEAR[YEAR_HUNDRED_END];
		
		for(int32 index = YEAR_FOUTH_HUNDRED;index > YEAR_HUNDRED_NONE;index--)
		{	
			if(time_left >= TIME_HUNDRED_YEAR[index])
			{
				year = 2001 + year_hundred_offset * FOUR_HUNDREAD_YEAR + index * ONE_HUNDREAD_YEAR;
				time_left = time_left - TIME_HUNDRED_YEAR[index];
				break;
			}
		}
	}
///<year process
	bool isLeapYear = false;
	{
		int32 year_offset = static_cast<int32>(time_left / TIME_YEAR[YEAR_END]);
		
		if(time_left < 0)
			--year_offset;
		
		time_left = time_left - TIME_YEAR[YEAR_END] * year_offset;
			
		for(int32 index = YEAR_FOUTH ;index > YEAR_NONE;--index)
		{
			if(time_left >= TIME_YEAR[index])
			{	
				time_left = time_left - TIME_YEAR[index];
				year += YEAR_END * year_offset + index;
				isLeapYear = (year % YEAR_END == 0 && year % ONE_HUNDREAD_YEAR != 0) || year % FOUR_HUNDREAD_YEAR == 0;
				
				break;
			}
		}
	}

///<month process
#define MONTH_CONVERT(MONTH_TYPE)	\
		{	\
			for(int32 index = MONTH_DEC;index > MONTH_NONE;--index)	\
			{	\
				if(time_left >= TIME_##MONTH_TYPE##_MONTH[index])	\
				{	\
					time_left = time_left - TIME_##MONTH_TYPE##_MONTH[index];	\
					month = index + 1;/* add one more because MONTH_JAN is begin at 1 */	\
					break;	\
				}	\
			}	\
		}
	
	{
		if(isLeapYear)
		{	
			for(int32 index = MONTH_DEC;index > MONTH_NONE;--index)	
			{	
				if(time_left >= TIME_LEAP_MONTH[index])
				{	
					time_left = time_left - TIME_LEAP_MONTH[index];
					month = index + 1;/* add one more because MONTH_JAN is begin at 1 */
					break;	
				}
			}
		}
		else
		{	
			for(int32 index = MONTH_DEC;index > MONTH_NONE;--index)	
			{	
				if(time_left >= TIME_COMMON_MONTH[index])
				{	
					time_left = time_left - TIME_COMMON_MONTH[index];
					month = index + 1;/* add one more because MONTH_JAN is begin at 1 */
					break;	
				}
			}
		}
	}
	
// 	{
// 		if(isLeapYear)
// 			MONTH_CONVERT(LEAP)
// 		else
// 			MONTH_CONVERT(COMMON)
// 		
// 	}
	
#undef MONTH_CONVERT
///<day process
	{
		int32 day_offset = static_cast<int32>(time_left / FELOWRIA_TIME_ONE_DAY);
		time_left = time_left - FELOWRIA_TIME_ONE_DAY * day_offset;
		day = day_offset + 1;//add one more because DAY is begin at 1
	}
	
///<week_day process
	{
		int32 week_day_offset = static_cast<int32>((time_value - int64(time_value / (WEEK_DAY_END * FELOWRIA_TIME_ONE_DAY)) * (WEEK_DAY_END * FELOWRIA_TIME_ONE_DAY)) / FELOWRIA_TIME_ONE_DAY);
		week_day = WEEK_DAY_THU + week_day_offset + (time_value < 0) * (-1);
		
		if(week_day >= WEEK_DAY_END)
			week_day -= WEEK_DAY_END;
		
		if(week_day < 0)
			week_day += WEEK_DAY_END;
	}
	
///<hour process
	{
		int32 hour_offset = static_cast<int32>(time_left / FELOWRIA_TIME_ONE_HOUR);
		time_left = time_left - FELOWRIA_TIME_ONE_HOUR * hour_offset;
		hour = hour_offset;
	}
	
///<minute process
	{
		int32 minute_offset = static_cast<int32>(time_left / FELOWRIA_TIME_ONE_MINUTE);
		time_left = time_left - FELOWRIA_TIME_ONE_MINUTE * minute_offset;
		minute = minute_offset;
	}
	
///<second process	
	{
		int32 second_offset = static_cast<int32>(time_left / FELOWRIA_TIME_ONE_SECOND);
		time_left = time_left - FELOWRIA_TIME_ONE_SECOND * second_offset;
		second = second_offset;
	}
	
///<micro_second process		
	{
		micro_second = static_cast<int32>(time_left / FELOWRIA_TIME_ONE_MICRO_SECOND);
	}

	time = time_value; 
	return (true);
}

FELOWRIA_END